#################
# Socket event Handling
#################
class Controller
  socket: null
  player: null
  user_me: null

  # callbacks for UI
  msg_authorized: null
  msg_added_tune: null   # notifying added the tune to the playlist
  msg_started_play: null
  msg_finished_publisher: null
  msg_finished_subscribe: null


  #
  # constructor
  #
  constructor:()->
    # @todo user info set
    @user_me = new UserInfo()
    @user_me.user_name = 'nato'
    @user_me.user_id = 0
    @player = PlayerFactory.create(this)
    return

  #
  # try connection to server
  #
  authorize:(sock_url)->
    if !@player?
      # @todo error handle
      throw new Error('AudioPlayer is not implemented')

    # Create WebSocket
    if window.MozWebSocket?
      @socket = new window.MozWebSocket(sock_url);
    else
      @socket = new window.WebSocket(sock_url);
    if !@socket?
      throw new Error('Failed in initializing socket')
    @socket.binaryType = 'arraybuffer'

    # Socket : on connection established
    @socket.onopen = (e)=>
      console.log 'connected then try authorize'
      @send_authorize_request()

    # Socket : on closed
    @socket.onclose  = ->
      console.log 'onclose'

    # Map socket handlers to player
    @socket.onmessage = (message)=>
      switch typeof message.data
        when 'string' then @received_json_message(message.data)
        else @received_stream_packet(message.data)
        # @todo error handling
    return

  #
  # Add my tune to playlist
  #
  add_playlist:(file)->
    tune = new Tune(file, file.name, @user_me.session_id)
    if tune?
      @player.add_tune(tune)
      @send_add_tune_request(tune)
    else
      throw new Error('invalid file')
    return

  #
  # start to play
  #
  start_play:(tune)->
    if tune.owner_session_id is @user_me.session_id
      @player.start_play_as_publisher(tune)
    else
      # @todo request to play
    return

  #
  # finalize
  #
  finalize:()->
    @socket.close()
    @socket = null
    return

  # ----------------------------------------------
  # socket on receive streaming buffer data
  # ----------------------------------------------
  received_stream_packet:(packet_data)->
    if @player.is_subscriber()
      packet = new StreamingPacket()
      packet.from_arraybuffer(packet_data)
      @player.on_receive_stream(packet.pcm_buff)
    return

  #
  # socket on receive json data
  #
  received_json_message:(json_data)->
    parsed_data = JSON.parse(json_data)
    console.log 'received_json_message:'+parsed_data.type
    switch parsed_data.type
      when 'authorized'
        @user_me.session_id = parsed_data.session_id
        @msg_authorized(@user_me)

      when 'added_tune'
        console.log parsed_data
        tune = new Tune(null, parsed_data.tune_name, parsed_data.owner_session_id)
        if tune.owner_session_id is @user_me.session_id
          # added by myself
          @player.tune_list.search_and_replace(tune)
        else
          # added by other
          @player.add_tune(tune)
        @msg_added_tune(tune)

      when 'started_playing'
        tune = new Tune(null, parsed_data.tune_name, parsed_data.owner_session_id)
        tune.requester_session_id = parsed_data.requester_id
        @player.tune_list.search_and_replace(tune)
        # Don't judge 'is_subscriber' because not started 'listen' yet.
        if !@player.is_publisher()
          @player.start_listen_as_subscriber()
          @msg_started_play(tune)

      when 'finished_publishing'
        if @player.is_subscriber()
          @player.stop_subscriber_node()
          @msg_finished_subscribe()
      
      else throw new Error('SocketHandler: unknown json type:' + parsed_data.type)
    return

  # ----------------------------------------------
  # send notify message
  # ----------------------------------------------
  send_string:(str_data)->
    @socket.send(str_data)
    return

  #
  # Send authorize reqeust
  # @todo 
  send_authorize_request:()->
    js_req = JSON.stringify({
        type: 'try_authorize'
      })
    @send_string(js_req)
    return

  #
  # Send add tune request 
  #
  send_add_tune_request:(tune)->
    send_json = 
      type: 'to_add_tune'
      session_id: @user_me.session_id
      tune_name: tune.name
    @send_string(JSON.stringify(send_json))
    return

  #
  # Send to start play notify
  #
  send_start_playing_request:(tune)->
    send_json = 
      type: 'start_playing'
      session_id: tune.owner_session_id
      requester_id : @user_me.session_id
      tune_name: tune.name
    @send_string(JSON.stringify(send_json))
    return

  #
  # Send audio streaming packet
  #
  send_audio_stream:(pcm_block)->
    packet = new StreamingPacket()
    packet.create_empty_packet(pcm_block[0].length, pcm_block.length)
    data = packet.to_array_buffer(@user_me.user_id, @user_me.session_id, pcm_block)
    # send as bynary
    #packet2 = new StreamingPacket()
    #packet2.from_arraybuffer(data)
    #console.log packet2.pcm_buff
    @socket.send(data)
    return

  send_finish_publishing:(tune)->
    send_json = 
      type: 'finish_publishing'
      session_id: tune.owner_session_id
      tune_name: tune.name
    @send_string(JSON.stringify(send_json))
    return

